import * as dayjs from 'dayjs';
import { BadRequestException, Inject, Injectable, OnModuleInit } from '@nestjs/common';
import { RedisService } from 'src/libs/redis/redis.service';
import { SpiderService } from 'src/libs/spider/spider.service';
import { getAllMatches, getMatchResults, getOddsHistory, getTeamHistoryMatches, getTeamRanking } from 'src/utils/init-data';
import { ConfigService } from '../config/config.service';
import { Cron, CronExpression } from '@nestjs/schedule';
import { OpenaiService } from 'src/libs/openai/openai.service';
import { AnalysisJson, getAnalysisPrompt } from 'src/prompt/analysis';
import getAiRecommendPrompt, { AIBettings, PredictionMap, StatusPredictionMap } from 'src/prompt/Ai-Recommend';
import { PrismaService } from 'src/libs/prisma/prisma.service';
import { HandicapStatus, MatchStatus } from '@prisma/client';
import { executeBatches } from 'src/utils';
import { resolveHandicapResult, resolveMatchResult } from 'src/utils/contains';
import { LogService } from 'src/libs/log/log.service';
import { WechatService } from 'src/libs/wechat/wechat.service';
import type { BET_TYPES, MatchData } from 'src/utils/init-data';
import * as timezone from 'dayjs/plugin/timezone';
import { EmailService } from 'src/libs/email/email.service';
dayjs.extend(timezone);

@Injectable()
export class DataService implements OnModuleInit {
  @Inject(RedisService)
  private readonly redisService: RedisService;
  @Inject(SpiderService)
  private readonly spiderService: SpiderService;
  @Inject(ConfigService)
  private readonly configService: ConfigService;
  @Inject(OpenaiService)
  private readonly openaiService: OpenaiService;
  @Inject(PrismaService)
  private readonly prismaService: PrismaService;
  @Inject(LogService)
  private readonly logService: LogService;
  @Inject(WechatService)
  private readonly wechatService: WechatService;
  @Inject(EmailService)
  private readonly emailService: EmailService;

  async onModuleInit() {
    this.getDailyMatches(process.env.NODE_ENV === 'production');
    // this.getDailyMatches();
    this.getMatchDataResult();
    // await this.deleteKeysByPrefix('20251111:OddsHistory');
  }

  /** 删除指定前缀的所有 Redis 键 */
  async deleteKeysByPrefix(prefix: string) {
    const pattern = `${prefix}*`;
    const deletedCount = await this.redisService.delByPattern(pattern);
    this.logService.info(`删除前缀为 ${prefix} 的键，共删除 ${deletedCount} 个`);
    return deletedCount;
  }

  /** 获取球队信息 */
  async getTeamInfo(teamName: string) {
    // 1 返回缓存数据
    // const key = `${this.configService.redisCahceFootballPrefix}:TeamInfo:${teamName}`;
    // const data = await this.redisService.get(key);
    // if (data?.trim()) return JSON.parse(data);
    // 2 获取数据
    const teamInfo = await this.spiderService.spiderBaiduAi(
      `请扮演一位顶级的足球分析师，对${teamName}进行一场全面、深度的剖析（基本信息、战术、关键球员、伤病情况、进攻、防守、状态、优劣势、心理因素等）`,
      'DS-R1',
      1,
    );
    // 3 存储数据
    // if (teamInfo) {
    //   await this.redisService.set(key, JSON.stringify(teamInfo), 48 * 60 * 60);
    // }
    // 4 返回数据
    return teamInfo;
  }

  /** 每三十分钟获取每日比赛数据 */
  @Cron(CronExpression.EVERY_30_MINUTES)
  async getDailyMatches(executeAnalyz = true) {
    // 1 获取数据
    this.logService.info('开始获取每日比赛数据');
    const result = await getAllMatches();

    // 2 更新已存在的数据/创建不存在的数据
    await this.prismaService.$transaction(
      result.map((item) =>
        this.prismaService.match.upsert({
          where: {
            matchId: item.matchId,
          },
          update: {
            matchData: JSON.stringify(item),
            matchTime: new Date(item.matchTime),
          },
          create: {
            matchId: item.matchId,
            matchData: JSON.stringify(item),
            matchTime: new Date(item.matchTime),
          },
        }),
      ),
    );

    // 3 获取需要分析的比赛
    const savedAnalysisMatches = await this.prismaService.matchAnalysis.findMany({
      where: {
        matchId: {
          in: result.map((item) => item.matchId),
        },
      },
    });
    const analysisMatches = result.filter(
      (item) => !savedAnalysisMatches.some((match) => match.matchId === item.matchId && match.analysisData !== '{}'),
    );

    // 4 分析比赛
    const analysisPromises: (() => Promise<void>)[] = [];
    for (const match of analysisMatches) {
      analysisPromises.push(() => this.analyzFootballMatch(match.matchId));
    }
    if (executeAnalyz) {
      console.log('需要分析的比赛数量：', analysisPromises.length);
      executeBatches(analysisPromises, +process.env.HANDLE_MATCH_TASK_NUM || 7);
    }
  }

  /** 获取球队历史比赛数据 */
  async getTeamHistoryMatches(teamId: string, homeAwayFlag?: 'home' | 'away') {
    // 1 返回缓存数据
    // const key = `${this.configService.redisCahceFootballPrefix}:TeamHistoryMatches:${teamId}${homeAwayFlag ? `-${homeAwayFlag}` : ''}`;
    // const data = await this.redisService.get(key);
    // if (data) {
    //   return {
    //     explan: '主队，客队，上半场比分，全场比分，时间',
    //     data: JSON.parse(data)
    //       .map((item) => `${item.homeAbbCnName}/${item.awayAbbCnName}/${item.sectionsNo1}/${item.sectionsNo999}/${item.matchDate}`)
    //       .join(','),
    //   };
    // }
    // 2 获取数据
    const result = await getTeamHistoryMatches({ gmTeamId: teamId, termLimits: homeAwayFlag ? 6 : 10, homeAwayFlag });
    // 3 存储数据
    // await this.redisService.set(key, JSON.stringify(result), 48 * 60 * 60);
    // 4 返回数据
    return {
      explan: '主队，客队，上半场比分，全场比分，时间',
      data: result
        .map((item) => `${item.homeAbbCnName}/${item.awayAbbCnName}/${item.sectionsNo1}/${item.sectionsNo999}/${item.matchDate}`)
        .join(','),
    };
  }

  /** 获取球队积分榜数据 */
  async getTeamRanking(gmMatchId: number) {
    // 1 返回缓存数据
    // const key = `${this.configService.redisCahceFootballPrefix}:TeamRanking:${gmMatchId}`;
    // const data = await this.redisService.get(key);
    // if (data) return JSON.parse(data);
    // 2 获取数据
    const result = await getTeamRanking({ gmMatchId });
    // 3 存储数据
    // await this.redisService.set(key, JSON.stringify(result), 48 * 60 * 60);
    // 4 返回数据
    return result;
  }

  /** 获取当天比赛天气情况 */
  async getWeather(match: MatchData) {
    // 1 返回缓存数据
    // const key = `${this.configService.redisCahceFootballPrefix}:Weather:${match.matchId}`;
    // const data = await this.redisService.get(key);
    // if (data) return JSON.parse(data);
    // 2 获取数据
    const result = await this.spiderService.spiderBaiduAi(`获取${match.homeTeam.name}和${match.awayTeam.name}当天比赛的天气情况`);
    // 3 存储数据
    // await this.redisService.set(key, JSON.stringify(result), 48 * 60 * 60);
    // 4 返回数据
    return result;
  }

  /** 获取比赛赔率变化 */
  async getOddsHistory(matchId: number, betType?: keyof typeof BET_TYPES) {
    // 1 返回缓存数据
    // const key = `${this.configService.redisCahceFootballPrefix}:OddsHistory:${matchId}${betType ? `-${betType}` : ''}`;
    // const data = await this.redisService.get(key);
    // if (data) return JSON.parse(data);
    // 2 获取数据
    const result = await getOddsHistory(matchId);
    // 3 存储数据
    // await this.redisService.set(key, JSON.stringify(result), 48 * 60 * 60);
    // 4 返回数据
    return result;
  }

  /** 分析比赛数据 */
  async analyzFootballMatch(matchId: number) {
    // 1 找到比赛
    const foundMatch = await this.prismaService.match.findUnique({
      where: { matchId },
      select: { matchData: true },
    });
    if (!foundMatch || !foundMatch.matchData) return;
    // 2 获取比赛存储数据
    const match = JSON.parse(foundMatch.matchData as string) as MatchData;
    const homeTeamId = match.homeTeam.id;
    const awayTeamId = match.awayTeam.id;
    console.log(`🚀 开始分析（${match.matchNum}）：${match.homeTeam.name} vs ${match.awayTeam.name}`);
    // 3 获取球队最近十场/主队六场/客队六场比赛数据
    const homeHistory1 = await this.getTeamHistoryMatches(homeTeamId);
    const awayHistory1 = await this.getTeamHistoryMatches(awayTeamId);
    const homeHistory2 = await this.getTeamHistoryMatches(homeTeamId, 'home');
    const awayHistory2 = await this.getTeamHistoryMatches(awayTeamId, 'away');
    // 4 获取主客积分榜数据
    const result = await this.getTeamRanking(matchId);
    // 5 获取比赛赔率变化
    // const oddsHistory = await this.getOddsHistory(matchId);
    // 6 获取球队信息
    const homeTeamInfo = await this.getTeamInfo(match.homeTeam.name);
    const awayTeamInfo = await this.getTeamInfo(match.awayTeam.name);
    // 7 当天比赛天气情况
    const weather = await this.getWeather(match);
    // 数据不足，直接取消分析
    if (!homeHistory1?.data || !awayHistory1?.data) {
      await this.prismaService.matchAnalysis.upsert({
        where: { matchId },
        update: { analysisData: '{ "rating": 0 }' },
        create: { matchId, analysisData: '{ "rating": 0 }' },
      });
      console.log(`✅ 数据不足，直接取消分析（${match.matchNum}）：${match.homeTeam.name} vs ${match.awayTeam.name}`);
      return;
    }

    // 8 分析数据
    const analysisData = await this.openaiService.excuteDeepSeek([
      ...getAnalysisPrompt(),
      {
        role: 'user',
        content: `这是一场${match.leagueName}的比赛，主队是${match.homeTeam.name}，客队是${match.awayTeam.name}, 比赛时间${match.matchTime}`,
      },
      {
        role: 'user',
        content: `比赛天气情况：${weather}`,
      },
      {
        role: 'user',
        content: `比赛数据每一项为${homeHistory1.explan},主队最近十场比赛数据：${homeHistory1.data}，客队最近十场比赛数据：${awayHistory1.data}，主队最近六场主场比赛数据：${homeHistory2.data}，客队最近六场客场比赛数据：${awayHistory2.data}`,
      },
      {
        role: 'user',
        content: `主队/客队积分榜数据：${JSON.stringify(result)}`,
      },
      // {
      //   role: 'user',
      //   content: `本场比赛赔率变化如下：${JSON.stringify(oddsHistory)}`,
      // },
      {
        role: 'user',
        content: `主队信息：${JSON.stringify(homeTeamInfo)}\n客队信息：${JSON.stringify(awayTeamInfo)}`,
      },
    ]);
    // 8 存储分析数据
    await this.prismaService.matchAnalysis.upsert({
      where: { matchId },
      update: { analysisData: JSON.stringify(analysisData) },
      create: { matchId, analysisData: JSON.stringify(analysisData) },
    });
    console.log(`✅ 分析完成（${match.matchNum}）：${match.homeTeam.name} vs ${match.awayTeam.name}`);
  }

  /** 获取比赛数据结果 */
  @Cron(CronExpression.EVERY_3_HOURS)
  async getMatchDataResult() {
    // 1 获取所有未开始的比赛
    this.logService.info('开始获取比赛数据结果');
    const matches = await this.prismaService.match.findMany({ where: { status: MatchStatus.NOT_STARTED } });

    // 2 获取比赛时间超过两小时的比赛
    const over120MinutesMatches = matches.filter((item) => {
      const matchTime = dayjs(item.matchTime);
      const diffMinutes = dayjs().diff(matchTime, 'minute');
      return diffMinutes >= 60 * 3;
    });

    // 3 保存比赛数据结果2
    for (const match of over120MinutesMatches) {
      const matchData = JSON.parse(match.matchData as string) as MatchData;
      const matchResult = await getMatchResults(match.matchId, matchData.homeTeam.id);
      const sectionsNos = matchResult.sectionsNos;
      if (!sectionsNos?.length) return;
      const [hadScore, fullScore, penaltyScore] = sectionsNos.sort((a, b) => a.sectionNo - b.sectionNo).map((item) => item.score);
      // 保存单场比赛的胜负情况
      await this.prismaService.match.update({
        where: { matchId: match.matchId },
        data: {
          hadScore,
          fullScore,
          penaltyScore,
          status: resolveMatchResult(fullScore),
          handicap: resolveHandicapResult(fullScore, +matchData.odds.hhad.goalLine),
        },
      });
    }
  }
}
